# Copyright (c) 2005,2006,2007 Dynamic Solutions Inc. (support@dynamic-solutions.com)
#
# This file is part of DataZoomer.
#
# DataZoomer is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# DataZoomer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""Quick Markup Language Translator

Pass a text string with QML (a Wiki-like language) in it and this function
will transform it into HTML
"""

class qml:
    def __init__(self):
        self.inlist = 0
        self.intable = 0

    def processline(self,text):
        def beginswith(text,key):
            return text[:len(key)] == key

        def process_markup(text,begin,end,callback):
            def inline_markup(text,begin,end):
                s1 = text.split(begin,1)
                if len(s1)>1:
                    s2 = s1[1].split(end,1)
                    if len(s2)>1:
                        return (s1[0],s2[0],s2[1])
                return None
            parts = inline_markup(text,begin,end)
            while parts:
                text = callback(parts)
                parts = inline_markup(text,begin,end)
            return text

        def set_bold(parts):
            return '%s<b>%s</b>%s' % parts

        def set_italics(parts):
            return '%s<i>%s</i>%s' % parts

        def set_link(parts):
            return '%s<a href="?sid=<#SID>&app=<#APP>&action=%s">%s</a>%s' % (parts[0],parts[1].replace(' ','_').lower(),parts[1],parts[2])

        def set_link2(parts):
            link_parts = parts[1].split('||')
            if len(link_parts)==3:
               return '%s<a class="%s" href="%s">%s</a>%s' % (parts[0],link_parts[2],link_parts[0],link_parts[1],parts[2])
            elif len(link_parts)==2:
               return '%s<a href="%s">%s</a>%s' % (parts[0],link_parts[0],link_parts[1],parts[2])
            elif len(link_parts)==1:
               return '%s<a href="%s">%s</a>%s' % (parts[0],link_parts[0],link_parts[0],parts[2])
               
        def set_red(parts):
            return '%s<font color=red>%s</font>%s' % parts

        t = ''
        if not beginswith(text,'*') and self.inlist:
            while self.inlist:
                t += '</ul>'
                self.inlist -= 1

        if not beginswith(text,'||') and self.intable:
            t += '</table>'
            self.intable = 0

        for word in text.split():
            if word[-4:].lower() in ['.jpg','.png','.gif']:
                text = text.replace(word,'<img src=%s>' % word)

        text = process_markup(text,"'''","'''",set_bold)
        text = process_markup(text,"''","''",set_italics)
        text = process_markup(text,"[[","]]",set_link)
        text = process_markup(text,"{{","}}",set_link2)
        text = process_markup(text,'%red%','%%',set_red)

        if beginswith(text,'!!!!'):
            t += '<H4>'+text[4:]+'</H4>'
        elif beginswith(text,'!!!'):
            t += '<H3>'+text[3:]+'</H3>'
        elif beginswith(text,'!!'):
            t += '<H2>'+text[2:]+'</H2>'
        elif beginswith(text,'!'):
            t += '<H1>'+text[1:]+'</H1>'
        elif text == '----':
            t += '<HR>'
        elif beginswith(text,'*'):

            level = 1
            if beginswith(text,'***'):
                level = 3
            elif beginswith(text,'**'):
                level = 2

            while self.inlist < level:
                self.inlist += 1
                t += '<ul class="level%s">' % level

            while self.inlist > level:
                self.inlist -= 1
                t += '</ul>'

            if beginswith(text,'***'):
                t += '<li class="level3">'+text[3:]+'</li>'
            elif beginswith(text,'**'):
                t += '<li class="level2">'+text[2:]+'</li>'
            elif beginswith(text,'*'):
                t += '<li class="level1"">'+text[1:]+'</li>'

        elif beginswith(text,'||'):
            if not self.intable:
                t += '<table %s class=usertable width="100%%" border=1>' % text[2:]
                self.intable = 1
            else:
                if text.strip()[-2:] == '||':
                    core = text.strip()[2:-2]
                else:
                    core = text[2:]
                q = qml()
                core = qml().qmltext(core)
                t += '<tr><td class=usertable>'+core.replace('||','</td><td class=usertable>')+'</td></tr>'

        else:
            t += text # + '<br>'

        return t

    def qmltext(self,text):
        self.inlist = 0
        lines = []

        text_lines = text.splitlines(0)
        blank_lines = 0
        for line in text_lines:
            if not line:
                blank_lines += 1
            else:
                break
        lines.append('<br>' * blank_lines)

        for line in text_lines:
#            if not (len(line) and line[0] == '#'):
#            if not (len(line)):
            lines += [self.processline(line)]
        if self.inlist:
            lines += ['</ul>']
        if self.intable:
            lines += ['</table>']
            

        result = ' '.join(lines)
#        if not (self.inlist or self.intable):
#        result = '<p>%s</p>' % result

        return result

    def qml(self,text):
        self.inlist = 0
        result = {}
        n = 1
        sections = text.replace('\r\n','\n').replace('\r','\n').split('\n====\n')
        for section in sections:
            paragraphs = section.split('\n\n')
            pp = []
            for paragraph in paragraphs:
                pp.append(self.qmltext(paragraph))
            name = 'PANEL%d' % n
            result[name] = ''.join(['%s' % item for item in pp])
            n += 1
        return result

    def convert(self,text):
        return self.qml(text)['PANEL1']

if __name__ == '__main__':
    import unittest

    class QmlTest(unittest.TestCase):

        def test_empty(self):
            p = qml()
            self.assertEqual(p.qmltext(""),"")

        def test_text(self):
            p = qml()
            self.assertEqual(p.qmltext("this is a test"),"<p>this is a test</p>")

        def test_convert(self):
            p = qml()
            self.assertEqual(p.convert("this is\n\na '''test'''."),"<p>this is</p><p>a <b>test</b>.</p>")

        def test_bold(self):
            p = qml()
            self.assertEqual(p.qmltext("this '''is''' a test"),"this <b>is</b> a test")

        def test_italic(self):
            p = qml()
            self.assertEqual(p.qmltext("this ''is'' a test"),"this <i>is</i> a test")

        def test_link(self):
            p = qml()
            self.assertEqual(p.qmltext('this link [[Do This]] is a test'),'this link <a href="?sid=<#SID>&app=<#APP>&action=do_this">Do This</a> is a test')

        def test_paragraph(self):
            p = qml()
            self.assertEqual(p.qml('This is para1\n\nthis is para2')['PANEL1'],'<p>This is para1</p><p>this is para2</p>')
            self.assertEqual(p.qml('This is para1\n\n\nthis is para2')['PANEL1'],'<p>This is para1</p><p><br>this is para2</p>')

        def test_panels(self):
            p = qml()
            self.assertEqual(p.qml("text1\n====\ntext2"),{'PANEL1':'text1','PANEL2':'text2'})

        def test_bullets(self):
            p = qml()
            self.assertEqual(p.qml("Test\n* One\n*Two\n* Three\n"),{'PANEL1':'Test<ul><li> One</li><li>Two</li><li> Three</li></ul>'})
            self.assertEqual(p.qmltext("Test\n* One\n*Two\n* Three\n"),'Test<ul><li> One</li><li>Two</li><li> Three</li></ul>')

    unittest.main()
